package com.budwk.app.sqfw.services.customservice;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.budwk.app.common.config.AppException;
import com.budwk.app.exception.ServiceException;
import com.budwk.app.sqfw.bo.RiverChiefBo;
import com.budwk.app.sqfw.constants.CommonConstants;
import com.budwk.app.sqfw.dto.RiverChiefAssistantDTO;
import com.budwk.app.sqfw.dto.TreeDTO;
import com.budwk.app.sqfw.models.Sqfw_formSummary_new;
import com.budwk.app.sqfw.services.SqfwFormsummaryNewService;
import com.budwk.app.sqfw.vo.SqfwCustomForAdminCommonVO;
import com.budwk.app.sys.models.Sys_unit;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.services.SysUnitService;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.util.ClassUtil;
import com.budwk.app.util.adminUtils.CommonCheckUtils;
import com.budwk.app.util.poiUtils.CommonFormOfficeUtils;
import com.budwk.app.util.poiUtils.PictureUtils;
import com.budwk.app.util.poiUtils.excelPictureConfigBO.ExcelFileCreateParamBO;
import com.budwk.starter.common.page.Pagination;
import com.budwk.starter.common.result.ResultCode;
import com.budwk.starter.security.utils.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.dao.util.cri.Static;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;

import java.util.*;

import static com.budwk.app.util.adminUtils.CommonCheckUtils.ZHISHU;

/**
 * 河长助手
 * @BelongsProject: dfxy-shequ
 * @Author: yangweimin
 * @CreateTime: 2024-06-28  10:11
 * @Description: TODO
 */
@IocBean
@Slf4j
public class RiverChiefService {
    @Inject
    private SqfwFormsummaryNewService sqfwFormsummaryNewService;
    @Inject
    private SysUserService sysUserService;
    @Inject
    private SysUnitService sysUnitService;

    /**
     * 获取数据
     * @param bean
     * @return
     */
    public Pagination list(SqfwCustomForAdminCommonVO bean) {
        // 构造查询条件
        Criteria criteria = buildQueryCond(bean);
        log.info("DoorThreeCareForAdminServiceImpl-list-SQL: {}", criteria.toString());
        Pagination pagination = sqfwFormsummaryNewService.listPage(bean.getPageNo(), bean.getPageSize(), criteria);

        List<Sqfw_formSummary_new> formSummaryNewList = pagination.getList(Sqfw_formSummary_new.class);
        if (formSummaryNewList.size() == 0) return pagination;

        Set<String> ids = new HashSet<>();
        for (Sqfw_formSummary_new formSummaryNew : formSummaryNewList) {
            ids.add(formSummaryNew.getCreateBy());
        }
        Cnd cnd = Cnd.NEW();
        cnd.and(Sys_user::getId, "in", ids);
        List<Sys_user> userList = sysUserService.query(cnd);
        for (Sys_user user : userList) {
            for (Sqfw_formSummary_new formSummaryNew : formSummaryNewList) {
                if (user.getId().equals(formSummaryNew.getCreateBy())) {
                    formSummaryNew.setCreateUserName(user.getUsername());
                }
            }
        }
        pagination.setList(formSummaryNewList);
        return pagination;
    }

    /**
     * 获取用户所属区域
     * @return
     */
    public TreeDTO getRegion() {
        Sys_user sysUser = sysUserService.getUserById(SecurityUtil.getUserId());

        Sys_unit sysUnit = sysUnitService.fetch(sysUser.getUnitId());
        
        return getName(sysUnit);
    }

    /**
     * 获取子单位
     * @param id
     * @return
     */
    public List<TreeDTO> getChild(String id) {
        Cnd cnd = Cnd.NEW();
        cnd.and(Sys_unit::getParentId, "=", id);
        List<Sys_unit> unitList = sysUnitService.query(cnd);
        List<TreeDTO> treeDTOList = new ArrayList<>();
        for (Sys_unit unit : unitList) {
            treeDTOList.add(getName(unit));
        }
        return treeDTOList;
    }

    /**
     * 检测是否存在下级节点
     * @param id
     * @return
     */
    public boolean hasChild(String id) {
        Cnd cnd = Cnd.NEW();
        cnd.and(Sys_unit::getParentId, "=", id);
        Sys_unit unit = sysUnitService.fetch(cnd);
        return unit != null ? true : false;
    }

    /**
     * 下载表格
     * @param bean
     * @return
     */
    public String downExcelByQuery(SqfwCustomForAdminCommonVO bean) {
        Criteria criteria = buildQueryCond(bean);
        List<Sqfw_formSummary_new> formSummaryNewList = sqfwFormsummaryNewService.query(criteria);

        Set<String> ids = new HashSet<>();
        for (Sqfw_formSummary_new formSummaryNew : formSummaryNewList) {
            ids.add(formSummaryNew.getCreateBy());
        }
        Cnd cnd = Cnd.NEW();
        cnd.and(Sys_user::getId, "in", ids);
        List<Sys_user> userList = sysUserService.query(cnd);
        for (Sys_user user : userList) {
            for (Sqfw_formSummary_new formSummaryNew : formSummaryNewList) {
                if (user.getId().equals(formSummaryNew.getCreateBy())) {
                    formSummaryNew.setCreateUserName(user.getUsername());
                }
            }
        }

        return downExcel(formSummaryNewList);
    }

    /**
     * 下载表格
     * @param idList
     * @return
     */
    public String downExcelByIds(List<String> idList) {
        if (idList.size() == 0) throw new ServiceException("请选择要导出的数据");
        Cnd cnd = Cnd.NEW();
        cnd.and(Sqfw_formSummary_new::getId, "in", idList);
        List<Sqfw_formSummary_new> formSummaryNewList = sqfwFormsummaryNewService.query(cnd);

        Set<String> ids = new HashSet<>();
        for (Sqfw_formSummary_new formSummaryNew : formSummaryNewList) {
            ids.add(formSummaryNew.getCreateBy());
        }
        Cnd cnd1 = Cnd.NEW();
        cnd1.and(Sys_user::getId, "in", ids);
        List<Sys_user> userList = sysUserService.query(cnd1);
        for (Sys_user user : userList) {
            for (Sqfw_formSummary_new formSummaryNew : formSummaryNewList) {
                if (user.getId().equals(formSummaryNew.getCreateBy())) {
                    formSummaryNew.setCreateUserName(user.getUsername());
                }
            }
        }

        return downExcel(formSummaryNewList);
    }

    public String downExcel(List<Sqfw_formSummary_new> formSummaryNewList) {
        if (formSummaryNewList.size() == 0) throw new ServiceException("暂无数据");
        List<Map<String, Object>> mapList = new ArrayList<>();
        int i = 0;
        for (Sqfw_formSummary_new formSummaryNew : formSummaryNewList) {
            Map<String, Object> map = new HashMap<>();
            i ++;
            RiverChiefAssistantDTO dto = JSON.parseObject(formSummaryNew.getParamData(), RiverChiefAssistantDTO.class);
            map.put("num", i);
            map.put(ClassUtil.getField(RiverChiefAssistantDTO::getRiverName), dto.getRiverName());
            map.put(ClassUtil.getField(RiverChiefAssistantDTO::getType), dto.getType());
            map.put(ClassUtil.getField(RiverChiefAssistantDTO::getAddress), dto.getAddress());
            map.put(ClassUtil.getField(RiverChiefAssistantDTO::getEventName), dto.getEventName());
            map.put(ClassUtil.getField(RiverChiefAssistantDTO::getAddress), dto.getAddress());
            map.put(ClassUtil.getField(RiverChiefAssistantDTO::getRiskDescription), dto.getRiskDescription());
            //图片处理
            List<byte[]> imgBytes = PictureUtils.scaleImageToByte(dto.getInspectionPhoto(), 1, false);
            map.put(ClassUtil.getField(RiverChiefAssistantDTO::getInspectionPhoto), imgBytes);
            map.put(ClassUtil.getField(Sqfw_formSummary_new::getUnitName), formSummaryNew.getUnitName());
            map.put(ClassUtil.getField(Sqfw_formSummary_new::getCreateUserName), formSummaryNew.getCreateUserName());
            map.put(ClassUtil.getField(Sqfw_formSummary_new::getFillDate), DateUtil.format(formSummaryNew.getFillDate(), "yyyy-MM-dd hh:mm:ss"));
            mapList.add(map);
        }

        String templatePath = CommonFormOfficeUtils.getTemplatePathByOS("helper/riverChief.xlsx");

        String fileName = "河长助手";

        ExcelFileCreateParamBO excelFileCreateParam = new ExcelFileCreateParamBO();
        excelFileCreateParam.setTemplatePath(templatePath);
        excelFileCreateParam.setSheetParam(new HashMap<>());
        excelFileCreateParam.setDataList(mapList);
        excelFileCreateParam.setClazz(RiverChiefBo.class);
        excelFileCreateParam.setFileName(fileName);
        excelFileCreateParam.setReturnWebUrlFlag(true);

        return CommonFormOfficeUtils.createExcelAndUpload(excelFileCreateParam);
    }
    
    private TreeDTO getName(Sys_unit unit) {
        // 市
        if (StringUtils.isBlank(unit.getCity()) || ZHISHU.equals(unit.getCity())) {
            return new TreeDTO(unit.getId(), unit.getProvince(), TreeDTO.P, hasChild(unit.getId()));
        }
        // 区
        if (StringUtils.isBlank(unit.getDistrict()) || ZHISHU.equals(unit.getDistrict())) {
            return new TreeDTO(unit.getId(), unit.getCity(), TreeDTO.C, hasChild(unit.getId()));
        }
        // 街道
        if (StringUtils.isBlank(unit.getCounty()) || ZHISHU.equals(unit.getCounty())) {
            return new TreeDTO(unit.getId(), unit.getDistrict(), TreeDTO.D, hasChild(unit.getId()));
        }
        // 辖区
        if (StringUtils.isBlank(unit.getCommunity()) || ZHISHU.equals(unit.getCommunity())) {
            return new TreeDTO(unit.getId(), unit.getCounty(), TreeDTO.J, hasChild(unit.getId()));
        }
        // 辖区
        if (StringUtils.isNotBlank(unit.getCommunity()) && !ZHISHU.equals(unit.getCommunity())) {
            return new TreeDTO(unit.getId(), unit.getCommunity(), TreeDTO.S, hasChild(unit.getId()));
        }

        return null;
    }

    public Criteria buildQueryCond(SqfwCustomForAdminCommonVO bean) {
        Criteria cri = Cnd.cri();
        SqlExpressionGroup criSql = cri.where();
        if (StringUtils.isEmpty(bean.getType())) {
            throw new AppException(ResultCode.NOT_FOUND.getMsg());
        }
        // 组装查询条件
        if (StringUtils.isNotBlank(bean.getPageOrderName()) && Strings.isNotBlank(bean.getPageOrderBy())) {
            if (bean.getPageOrderBy().equals(CommonConstants.ASC)) {
                cri.getOrderBy().asc(bean.getPageOrderName());
            }
            if (bean.getPageOrderBy().equals(CommonConstants.DESC)) {
                cri.getOrderBy().desc(bean.getPageOrderName());
            }
        } else {
            cri.getOrderBy().desc(Sqfw_formSummary_new::getFillDate);
        }
        // 类型
        criSql.andEquals(SqfwCustomForAdminCommonVO::getType, bean.getType());

        if (StringUtils.isNotBlank(bean.getQueryAll())) {
            SqlExpressionGroup riverName = Cnd.exps(new Static("param_data->>'riverName' like '%" + bean.getQueryAll() + "%'"));
            SqlExpressionGroup eventName = Cnd.exps(new Static("param_data->>'eventName' like '%" + bean.getQueryAll() + "%'"));
            criSql.and(riverName.or(eventName));
        }
        if (bean.getFillStartDate() != null) {
            criSql.and(Sqfw_formSummary_new::getFillDate, ">=", bean.getFillStartDate());
        }
        if (bean.getFillEndDate() != null) {
            criSql.and(Sqfw_formSummary_new::getFillDate, "<=", bean.getFillEndDate());
        }
        if (StringUtils.isNotBlank(bean.getRiverName())) {
            criSql.and("param_data->>'riverName'", "=", bean.getRiverName());
        }
        if (StringUtils.isNotBlank(bean.getRiverType())) {
            criSql.and("param_data->>'type'", "=", bean.getRiverType());
        }

        // 设置五级
        if (StringUtils.isBlank(bean.getUnitId())) {
            CommonCheckUtils.checkAreaRange(criSql);
        } else {
            setCriSql(criSql, bean.getUnitId());
        }
        
        return cri;
    }

    /**
     * 设置五级
     * @param criSql
     * @param unitId  前端传来的 五级区域id
     */
    private void setCriSql(SqlExpressionGroup criSql, String unitId) {
        String sql = "WITH RECURSIVE dict AS (" +
                "     SELECT *" +
                "     FROM shequ.sys_unit" +
                "     WHERE id = '"+unitId+"'" +
                "     union ALL" +
                "     SELECT shequ.sys_unit.*" +
                "     FROM shequ.sys_unit," +
                "          dict" +
                "     WHERE shequ.sys_unit.id = dict.parentid" +
                ")" +
                "SELECT * FROM dict";
        List<Sys_unit> unitList = sysUnitService.listEntity(Sqls.create(sql));

        // LinkedHashSet能保证元素添加的顺序
        Set<String> set = new LinkedHashSet<>();
        for (Sys_unit unit : unitList) {
            if (StringUtils.isNotBlank(unit.getProvince()) && !ZHISHU.equals(unit.getProvince())) {
                set.add(unit.getProvince());
            }
        }
        for (Sys_unit unit : unitList) {
            if (StringUtils.isNotBlank(unit.getCity()) && !ZHISHU.equals(unit.getCity())) {
                set.add(unit.getCity());
            }
        }
        for (Sys_unit unit : unitList) {
            if (StringUtils.isNotBlank(unit.getDistrict()) && !ZHISHU.equals(unit.getDistrict())) {
                set.add(unit.getDistrict());
            }
        }
        for (Sys_unit unit : unitList) {
            if (StringUtils.isNotBlank(unit.getCounty()) && !ZHISHU.equals(unit.getCounty())) {
                set.add(unit.getCounty());
            }
        }
        for (Sys_unit unit : unitList) {
            if (StringUtils.isNotBlank(unit.getCommunity()) && !ZHISHU.equals(unit.getCommunity())) {
                set.add(unit.getCommunity());
            }
        }

        int i = 0;
        for (String name : set) {
            setSql(criSql, i, name);
            i ++;
        }
    }

    private void setSql(SqlExpressionGroup criSql, int i, String name) {
        switch (i) {
            case 0:
                criSql.andEquals(Sys_user::getProvince, name);
                break;
        }
        switch (i) {
            case 1:
                criSql.andEquals(Sys_user::getCity, name);
                break;
        }
        switch (i) {
            case 2:
                criSql.andEquals(Sys_user::getDistrict, name);
                break;
        }
        switch (i) {
            case 3:
                criSql.andEquals(Sys_user::getCounty, name);
                break;
        }
        switch (i) {
            case 4:
                criSql.andEquals(Sys_user::getCommunity, name);
                break;
        }
    }
}
